package com.ruoyi.manage.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.YearMonth;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.manage.domain.*;
import com.ruoyi.manage.mapper.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.manage.service.ISalSalaryService;

/**
 * 薪资Service业务层处理
 * 
 * @author cf
 * @date 2025-06-05
 */
@Service
public class SalSalaryServiceImpl implements ISalSalaryService 
{
    private static final Logger log = LoggerFactory.getLogger(SalSalaryServiceImpl.class);
    @Autowired
    private SalSalaryMapper salSalaryMapper;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private AttOvertimeMapper attOvertimeMapper;

    @Autowired
    private SalSalaryDeductMapper salaryDeductMapper;
    
    @Autowired
    private DeptWorkScheduleMapper deptWorkScheduleMapper;

    @Autowired
    private AttAttendanceMapper attAttendanceMapper;

    @Autowired
    private SocInsuranceMapper socInsuranceMapper;

    @Autowired
    private EmpContractSalaryMapper empContractMapper;

    /**
     * 查询薪资
     * 
     * @param id 薪资主键
     * @return 薪资
     */
    @Override
    public SalSalary selectSalSalaryById(Long id)
    {
        return salSalaryMapper.selectSalSalaryById(id);
    }

    /**
     * 查询薪资列表
     * 
     * @param salSalary 薪资
     * @return 薪资
     */
    @Override
    public List<SalSalary> selectSalSalaryList(SalSalary salSalary)
    {
        return salSalaryMapper.selectSalSalaryList(salSalary);
    }

    /**
     * 新增薪资
     * 
     * @param salSalary 薪资
     * @return 结果
     */
    @Override
    public int insertSalSalary(SalSalary salSalary)
    {
        salSalary.setCreateTime(DateUtils.getNowDate());
        return salSalaryMapper.insertSalSalary(salSalary);
    }

    /**
     * 修改薪资
     * 
     * @param salSalary 薪资
     * @return 结果
     */
    @Override
    public int updateSalSalary(SalSalary salSalary)
    {
        salSalary.setUpdateTime(DateUtils.getNowDate());
        return salSalaryMapper.updateSalSalary(salSalary);
    }

    /**
     * 批量删除薪资
     * 
     * @param ids 需要删除的薪资主键
     * @return 结果
     */
    @Override
    public int deleteSalSalaryByIds(Long[] ids)
    {
        return salSalaryMapper.deleteSalSalaryByIds(ids);
    }

    /**
     * 删除薪资信息
     * 
     * @param id 薪资主键
     * @return 结果
     */
    @Override
    public int deleteSalSalaryById(Long id)
    {
        return salSalaryMapper.deleteSalSalaryById(id);
    }

    /**
     * @param staffId
     * @param format
     * @return
     */
    @Override
    public List<SalSalary> calculateSalary(Long staffId, String format) {
        if (staffId == null) {
            throw new IllegalArgumentException("员工ID不能为空");
        }

        if (format == null || format.trim().isEmpty()) {
            throw new IllegalArgumentException("月份格式不能为空");
        }
        EmpContractSalary empContractSalary = empContractMapper.selectEmpContractSalaryBySalaryId(staffId);
        log.info("员工ID：{}", staffId);
        log.info("月份：{}", format);
        log.info("EmpContractSalary：{}", empContractSalary);
        BigDecimal baseSalary = empContractSalary.getBaseSalary();
        BigDecimal baseSalaryOnce = baseSalary;
        BigDecimal baseAllowance = empContractSalary.getAllowance();
        BigDecimal baseBonus = empContractSalary.getBonus();
        SocInsurance socInsurance = socInsuranceMapper.selectSocInsuranceById(staffId);
        log.info(" SocInsurance：{}", socInsurance);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        sdf.setLenient(false); // 关闭宽松解析模式
        Date beginTime;
        Date endTime;
        try {
            YearMonth yearMonth = YearMonth.parse(format);
            beginTime = Date.from(yearMonth.atDay(1)
                    .atStartOfDay(ZoneId.systemDefault())
                    .toInstant());

            endTime = Date.from(yearMonth.atEndOfMonth()
                    .atStartOfDay(ZoneId.systemDefault())
                    .plusDays(1)
                    .minusNanos(1)
                    .toInstant());

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        List<AttAttendanceSummary> staffMonthAttendanceSummary  = attAttendanceMapper.selectAttendanceSummaryByPeriod("month", null, beginTime, endTime,staffId);
        log.info(" staffMonthAttendanceSummary：{}", staffMonthAttendanceSummary);
        Staff staff = staffMapper.selectStaffById(staffId);
        log.info(" staff：{}", staff);
        DeptWorkSchedule deptWorkSchedule = new DeptWorkSchedule();

        deptWorkSchedule.setDeptId(staff.getDeptId());
        List<DeptWorkSchedule> deptWorkSchedules = deptWorkScheduleMapper.selectDeptWorkScheduleList(deptWorkSchedule);
        if (deptWorkSchedules != null && !deptWorkSchedules.isEmpty()) {
            deptWorkSchedule = deptWorkSchedules.get(0);
        } else {
            log.warn("未找到部门工作排班信息，staffId={}", staffId);
            // 可根据业务逻辑决定是否跳过该员工或设置默认值
            return null;
        }
        log.info(" deptWorkSchedules：{}", deptWorkSchedules);
        deptWorkSchedule = deptWorkSchedules.get(0);
        AttOvertime overtime = new AttOvertime();
        overtime.setDeptId(staff.getDeptId());
        overtime.setUpdateTime(new Date());
        BigDecimal overtimesSalary = BigDecimal.ZERO;
        List<AttOvertime> attOvertimes = attOvertimeMapper.selectAttOvertimeList(overtime);
        log.info(" attOvertimes：{}", attOvertimes);
        for (AttOvertime attOvertime : attOvertimes)
        {
            Integer isTimeOff = attOvertime.getIsTimeOff();
            if(isTimeOff==1)
            {
                continue;
            }
            BigDecimal salaryMultiple = attOvertime.getSalaryMultiple();
            BigDecimal workHours = attOvertime.getWorkHours();
            BigDecimal salaryOnce = baseSalary.divide(new BigDecimal("21.75"), 2, RoundingMode.HALF_UP)
                    .divide(deptWorkSchedule.getTotalHours(), 2, RoundingMode.HALF_UP)
                    .multiply(salaryMultiple)
                    .multiply(workHours);

            log.info("加班工资："+salaryOnce);
            baseSalary = baseSalary.add(salaryOnce);
            overtimesSalary=overtimesSalary.add(salaryOnce);
            log.info("加班工资："+salaryOnce);
            BigDecimal bonus = attOvertime.getBonus();
            baseSalary=baseSalary.add(bonus);
            baseBonus = baseBonus.add(bonus);
            log.info("奖金："+bonus);
            overtimesSalary=overtimesSalary.add(bonus);
        }
        baseSalary = baseSalary.add(baseAllowance);
//        attAttendanceMapper.selectAttendanceSummaryByPeriod("month",null,new Date(format),new Date(format));
        SalSalaryDeduct salSalaryDeduct=new SalSalaryDeduct();
        salSalaryDeduct.setDeptId(staff.getDeptId());
        AttAttendanceSummary attAttendanceSummary = staffMonthAttendanceSummary.get(0);
        List<SalSalaryDeduct> salSalaryDeducts = salaryDeductMapper.selectSalSalaryDeductList(salSalaryDeduct);
        log.info("salSalaryDeducts:{}",salSalaryDeducts);
        BigDecimal lateDaysSalary = new BigDecimal(0);
        BigDecimal earlyLeaveDaysSalary = new BigDecimal(0);
        BigDecimal absentDaysSalary = new BigDecimal(0);
        BigDecimal leaveDaysSalary = new BigDecimal(0);
        for (SalSalaryDeduct salaryDeduct : salSalaryDeducts)
        {
            Integer deductType = salaryDeduct.getDeductType();
            Long deductAmount = salaryDeduct.getDeductAmount();
            if(deductType==2)
            {
                BigDecimal late = new BigDecimal(deductAmount).multiply(new BigDecimal(attAttendanceSummary.getLateDays()));
                baseSalary=baseSalary.subtract(late);
                lateDaysSalary=lateDaysSalary.add(late);
                log.info("迟到金额："+late);
            }
            else if(deductType==3)
            {
                BigDecimal early = new BigDecimal(deductAmount).multiply(new BigDecimal(attAttendanceSummary.getEarlyLeaveDays()));
                baseSalary=baseSalary.subtract(early);
                earlyLeaveDaysSalary=earlyLeaveDaysSalary.add(early);
                log.info("早退金额："+early);
            } else if (deductType ==4) {
                BigDecimal absent = new BigDecimal(deductAmount).multiply(new BigDecimal(attAttendanceSummary.getAbsentDays()));
                baseSalary=baseSalary.subtract(absent);
                absentDaysSalary=absentDaysSalary.add(absent);
                log.info("旷工金额："+absent);
            } else if (deductType == 5) {
                BigDecimal leave = new BigDecimal(deductAmount).multiply(new BigDecimal(attAttendanceSummary.getLeaveDays()));
                baseSalary =baseSalary.subtract(leave);
                leaveDaysSalary=leaveDaysSalary.add(leave);
                log.info("请假金额："+leave);
            }

        }
        baseSalary = baseSalary.subtract(socInsurance.getSocialBase()).subtract(socInsurance.getHouseBase());
        SalSalary salSalary = new SalSalary();
        salSalary.setStaffId(staffId);
        salSalary.setBaseSalary(baseSalaryOnce);
        salSalary.setAbsenteeismDeduct(absentDaysSalary);
        salSalary.setLeaveEarlyDeduct(earlyLeaveDaysSalary);
        salSalary.setLateDeduct(lateDaysSalary);
        salSalary.setPutOffDeduct(leaveDaysSalary);
        salSalary.setOvertimeSalary(overtimesSalary);
        salSalary.setSubsidy(baseAllowance);
        salSalary.setBonus(baseBonus);
        salSalary.setTotalSalary(baseSalary);
        salSalary.setHouseBase(socInsurance.getHouseBase());
        salSalary.setIndividualHouseRate(socInsurance.getIndividualHouseRate());
        salSalary.setIndividualHousePay(socInsurance.getIndividualHousePay());
        salSalary.setSocialBase(socInsurance.getSocialBase());
        salSalary.setIndividualSocialPay(socInsurance.getIndividualSocialPay());
        salSalary.setNowMonth(format);
        salSalary.setIsDeleted(0);
        log.info("插入数据："+salSalary);
        int res=salSalaryMapper.insertSalSalary(salSalary);
        List<SalSalary> list=new ArrayList<>();
        if(res>0)
        {
            list.add(salSalary);
            return list;
        }
        return null;
    }
}
